package com.jishuo.pzk.util;

import com.jishuo.pzk.bean.base.ImageVO;
import com.jishuo.pzk.bean.base.VoucherDetailVO;
import lombok.extern.slf4j.Slf4j;
import sun.font.FontDesignMetrics;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.font.FontRenderContext;
import java.awt.geom.AffineTransform;
import java.awt.geom.Rectangle2D;
import java.awt.image.AffineTransformOp;
import java.awt.image.BufferedImage;
import java.io.*;
import java.util.List;

/**
 * 图片工具类， 图片水印，文字水印，缩放，补白等
 */
@Slf4j
public class ImageUtils {

    /**
     * 图片格式：JPG
     */
    private static final String PICTRUE_FORMATE_JPG = "jpg";

    /**
     * 将颜色转换为字符串形式的颜色码
     *
     * @param color 颜色对象
     * @return 返回颜色码字符串
     */
    public static String Color2String(Color color) {
        String R = Integer.toHexString(color.getRed()); // 将红分量转换为16进制字符串
        R = R.length() < 2 ? ('0' + R) : R; // 如果红分量的长度小于2，则在前面补0
        String B = Integer.toHexString(color.getBlue()); // 将蓝分量转换为16进制字符串
        B = B.length() < 2 ? ('0' + B) : B; // 如果蓝分量的长度小于2，则在前面补0
        String G = Integer.toHexString(color.getGreen()); // 将绿分量转换为16进制字符串
        G = G.length() < 2 ? ('0' + G) : G; // 如果绿分量的长度小于2，则在前面补0
        return '#' + R + B + G; // 返回拼接后的RGB颜色字符串

    }

    /**
     * 将颜色码字符串转换为颜色对象
     *
     * @param str 颜色码字符串
     * @return 返回颜色对象
     */
    public static Color String2Color(String str) {
        int i = Integer.parseInt(str.substring(1), 16);
        return new Color(i);
    }

    /**
     * 获取字体所占宽度
     *
     * @param font    字体格式
     * @param content 字体内筒
     * @return 返回宽度
     */
    public static int getWordWidth(Font font, String content) {
        // 创建字体渲染上下文
        FontRenderContext frc = new FontRenderContext(null, true, true);
        // 获取字符串的边界矩形
        Rectangle2D bounds = font.getStringBounds(content, frc);
        // 返回矩形宽度的整数值
        return (int) bounds.getWidth();

    }

    /**
     * 在图片上绘制文字列表
     *
     * @param targetImg 目标图片字节数组
     * @param list      文字列表
     * @return 目标图片字节数组经过绘制文字操作后的结果
     * @throws Exception
     */
    public static byte[] pressTextList(byte[] targetImg, List<VoucherDetailVO> list) throws Exception {

        log.info("开始画图");
        // 读取目标图像
        Image image = ImageIO.read(new ByteArrayInputStream(targetImg));
        // 获取图像宽度
        int width = image.getWidth(null);
        // 获取图像高度
        int height = image.getHeight(null);
        // 创建一个新的缓冲图像
        BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        // 创建绘图对象
        Graphics2D g = bufferedImage.createGraphics();

        // 在缓冲图像上绘制图像
        g.drawImage(image, 0, 0, width, height, null);


        log.info("开始循环，共计" + list.size() + "条数据");

        for (VoucherDetailVO iv : list) {
            String valueString = iv.getFieldValue();  // 获取字段的值

            if (iv.getFieldValue() == null || "".equals(iv.getFieldValue())) {  // 如果字段的值为空
                valueString = "";  // 将值设为空字符串
            }

            g.setFont(new Font(iv.getFontname(), Font.PLAIN, iv.getFontsize()));  // 设置字体
            g.setColor(String2Color(iv.getFontcolor()));  // 设置字体颜色
            g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, iv.getAlpha()));  // 设置混合模式


            if (valueString != null && !valueString.equals("")) {
                // 如果MAXLENGTH为空或者为0
                if (iv.getMaxlength() == null || iv.getMaxlength() == 0) {
                    int x;

                    // 如果对齐方式为"right"
                    if ("right".equals(iv.getHalign())) {
                        // 计算x坐标，根据字体、粗细和值的字符串获取文本宽度，然后将x坐标减去文本宽度
                        x = iv.getX() - getWordWidth(new Font(iv.getFontname(), Font.PLAIN, iv.getFontsize()), valueString);
                        // 如果对齐方式为"center"
                    } else if ("center".equals(iv.getHalign())) {
                        // 获取文本宽度
                        int xx = getWordWidth(new Font(iv.getFontname(), Font.PLAIN, iv.getFontsize()), valueString);
                        // 计算x坐标，根据x坐标、文本宽度和xx坐标减去x坐标减去文本宽度的结果除以2
                        x = iv.getX() + (iv.getXx() - iv.getX() - xx) / 2;
                    } else {
                        // x坐标等于iv中的x坐标
                        x = iv.getX();
                    }

                    // 在指定的x和y坐标上绘制字符串
                    g.drawString(valueString, x, iv.getY());
                } else {
                    // 其他情况
                    // 如果iv中的ISNEWLINE不为空且等于1
                    if (iv.getIsnewline() != null && iv.getIsnewline().equals("1")) {
                        // 如果valueString的长度小于等于最大长度
                        if (valueString.length() <= iv.getMaxlength()) {
                            int x;

                            // 如果对齐方式为right
                            if ("right".equals(iv.getHalign())) {
                                // 计算x为iv中的X减去valueString的字宽
                                x = iv.getX() - getWordWidth(new Font(iv.getFontname(), Font.PLAIN, iv.getFontsize()), valueString);
                            }
                            // 如果对齐方式为center
                            else if ("center".equals(iv.getHalign())) {
                                // 计算x为iv中的X加上xx减去X再减去valueString的字宽除以2
                                int xx = getWordWidth(new Font(iv.getFontname(), Font.PLAIN, iv.getFontsize()), valueString);
                                x = iv.getX() + (iv.getXx() - iv.getX() - xx) / 2;
                            } else {
                                // x为iv中的X
                                x = iv.getX();
                            }

                            // 在画布g上绘制valueString，位置为(x, iv中的Y)
                            g.drawString(valueString, x, iv.getY());
                        } else {
                            // 计算chu为valueString的长度除以最大长度向上取整
                            int chu = (int) Math.ceil((double) valueString.length() / (double) iv.getMaxlength());

                            // 遍历chu
                            for (int j = 0; j < chu; j++) {
                                // 获取画布g中字体的度量对象
                                FontMetrics fm = g.getFontMetrics(new Font(iv.getFontname(), Font.PLAIN, iv.getFontsize()));
                                // 定义textTem为valueString的子串
                                String textTem;

                                // 如果valueString的长度小于最大长度乘以(j+1)
                                if (valueString.length() < iv.getMaxlength() * (j + 1)) {
                                    // textTem为valueString的前j*最大长度个字符
                                    textTem = valueString.substring(j * iv.getMaxlength());
                                } else {
                                    // textTem为valueString的前j*最大长度个字符到(iv.getMaxlength() * (j + 1)) - 1个字符
                                    textTem = valueString.substring(j * iv.getMaxlength(), iv.getMaxlength() * (j + 1));
                                }

                                int x;

                                // 如果对齐方式为right
                                if ("right".equals(iv.getHalign())) {
                                    // x为iv中的X减去textTem的字宽
                                    x = iv.getX() - getWordWidth(new Font(iv.getFontname(), Font.PLAIN, iv.getFontsize()), textTem);
                                }
                                // 如果对齐方式为center
                                else if ("center".equals(iv.getHalign())) {
                                    // 计算x为iv中的X加上xx减去X再减去textTem的字宽除以2
                                    int xx = getWordWidth(new Font(iv.getFontname(), Font.PLAIN, iv.getFontsize()), textTem);
                                    x = iv.getX() + (iv.getXx() - iv.getX() - xx) / 2;
                                } else {
                                    // x为iv中的X
                                    x = iv.getX();
                                }

                                // 在画布g上绘制textTem，位置为(x, iv中的Y + j * 字体的高度)
                                g.drawString(textTem, x, iv.getY() + j * fm.getHeight());
                            }
                        }
                    } else {
                        String textTem;

                        if (valueString.length() > iv.getMaxlength()) {
                            textTem = valueString.substring(0, iv.getMaxlength());
                        } else {
                            textTem = valueString;
                        }

                        int x;

                        if ("right".equals(iv.getHalign())) {
                            x = iv.getX() - getWordWidth(new Font(iv.getFontname(), Font.PLAIN, iv.getFontsize()), textTem);
                        } else if ("center".equals(iv.getHalign())) {
                            int xx = getWordWidth(new Font(iv.getFontname(), Font.PLAIN, iv.getFontsize()), textTem);
                            x = iv.getX() + (iv.getXx() - iv.getX() - xx) / 2;
                        } else {
                            x = iv.getX();
                        }

                        g.drawString(textTem, x, iv.getY());
                    }
                }
            }
        }

        // 释放资源
        g.dispose();
        // 创建一个ByteArrayOutputStream对象
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        // 将缓冲图像转换为指定格式的图片，并写入到输出流中
        ImageIO.write(bufferedImage, PICTRUE_FORMATE_JPG, out);

        log.info("结束画图");

        return out.toByteArray();
    }

    /**
     * 添加图片水印
     *
     * @param targetImg 目标图片路径，如：C://myPictrue//1.jpg
     * @param waterImg  水印图片路径，如：C://myPictrue//logo.png
     * @param x         水印图片距离目标图片左侧的偏移量，如果x<0, 则在正中间
     * @param y         水印图片距离目标图片上侧的偏移量，如果y<0, 则在正中间
     * @param alpha     透明度(0.0 -- 1.0, 0.0为完全透明，1.0为完全不透明)
     * @return 目标图片字节数组经过添加水印操作后的结果
     */
    public static byte[] pressImage(byte[] targetImg, byte[] waterImg, int x, int y, float alpha) {
        try {
            // 读取目标图片
            Image image = ImageIO.read(new ByteArrayInputStream(targetImg));
            // 获取图片的宽度
            int width = image.getWidth(null);
            // 获取图片的高度
            int height = image.getHeight(null);
            // 创建一个与目标图片相同大小的缓冲图像
            BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
            // 获取缓冲图像的图形上下文
            Graphics2D g = bufferedImage.createGraphics();
            // 在缓冲图像上绘制目标图片
            g.drawImage(image, 0, 0, width, height, null);

            // 读取水印图片
            Image waterImage = ImageIO.read(new ByteArrayInputStream(waterImg));
            // 获取水印图片的宽度
            int width_1 = waterImage.getWidth(null);
            // 获取水印图片的高度
            int height_1 = waterImage.getHeight(null);
            // 设置图形上下文字的组合方式为SRC_ATOP，透明度为alpha
            g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, alpha));
            // 在缓冲图像上绘制水印图片
            g.drawImage(waterImage, x, y, width_1, height_1, null); // 水印文件结束
            // 释放图形上下文资源
            g.dispose();
            // 创建一个字节数组输出流
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            // 将缓冲图像保存为图片并写入输出流
            ImageIO.write(bufferedImage, PICTRUE_FORMATE_JPG, out);
            // 返回输出流中的字节数组
            return out.toByteArray();
        } catch (IOException e) {
            // 打印异常堆栈信息
            e.printStackTrace();
        }
        return null;
    }
}
